﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Engine.Plot;
using log4net;
using Engine;
using System.Data.Common;
using System.Data;

namespace ResearchDemonstration.DAO
{
    
    /// <summary>
    /// Perform and encapsulate database operations.
    /// </summary>
    public class DatabaseManager
    {
        /// <summary>
        /// Log
        /// </summary>
        private readonly ILog Log = LogManager.GetLogger(typeof(DatabaseManager));
        /// <summary>
        /// throw this class we access database
        /// </summary>
        private DatabaseEntities _entities;
        
        /// <summary>
        /// Standart constructor
        /// </summary>
        public DatabaseManager()
        {
            _entities = new DatabaseEntities();
        }

        /// <summary>
        /// Add new finded value to database
        /// </summary>
        /// <param name="plotPoint">finded value</param>
        public void AddRecord(PlotPoint plotPoint)
        {
            try
            {
                _entities.Connection.Open();
                var maxIdRecord = (from r in _entities.Results orderby r.result_id descending select r).FirstOrDefault();
                long newId = 0;
                if(maxIdRecord != null)
                {
                    newId = maxIdRecord.result_id + 1;                
                }
                //create entity that record to database
                Results result = Results.CreateResults(newId,plotPoint.X,plotPoint.Conductance,DateTime.Now);
                result.lattice_id = (int) plotPoint.LatticeId;
                result.type = (int) plotPoint.Type;
                result.element_conductance = plotPoint.ElementConductance;
                _entities.AddToResults(result);
                //commit to database
                _entities.SaveChanges();
            }
            catch (Exception e)
            {
                if(Log.IsDebugEnabled)
                {
                    Log.Debug("произошла ошибка при работе с базой", e);
                }
                throw e;
            }
            finally
            {
                _entities.Connection.Close();
            }
        }

        /// <summary>
        /// get all data from database for statistical calculation
        /// </summary>
        /// <returns>map where key is id of square lattice and value list of results for this lattice.</returns>
        public IDictionary<int, IList<PlotPoint>> getAllData() 
        { 
            //todo - maybe we need to  do not store all data in memory location
            //and serializably read it from database
            IDictionary<int, IList<PlotPoint> > data = new Dictionary<int, IList<PlotPoint>>();
            try
            {
                _entities.Connection.Open();
                //seriesPercolationThreashold we must get list of all entities
                DbConnection conn = _entities.Connection;
                DbCommand command = conn.CreateCommand();
                
                command.CommandText = "SELECT VALUE p FROM DatabaseEntities.Results AS p";
                DbDataReader dr = command.ExecuteReader(CommandBehavior.SequentialAccess);
                IList<int> lattice_ids = new List<int>(100); //optimization
                while (dr.Read()) 
                {
                    int latticeId = dr.GetInt32(4);
                    if(!lattice_ids.Contains(latticeId))
                    {
                        lattice_ids.Add( latticeId );
                    }
                }
                dr.Close();
                
                foreach(int latticeId in lattice_ids)
                {
                    IList<Results> results = (from r in _entities.Results where r.lattice_id == latticeId orderby r.x descending select r).ToList();
                    IList<PlotPoint> latticeData = new List<PlotPoint>();
                    foreach(Results result in results)
                    {
                        PlotPoint record = new PlotPoint(result.x, result.conductance, (long) result.lattice_id, (ResultType) result.type);
                        record.ElementConductance = (double) result.element_conductance;
                        latticeData.Add(record);
                    }
                    data[latticeId] = latticeData;
                }
            }
            catch (Exception e)
            {
                if (Log.IsDebugEnabled)
                {
                    Log.Debug("произошла ошибка при работе с базой", e);
                }
                throw e;
            }
            finally
            {
                if (_entities.Connection.State == System.Data.ConnectionState.Open)
                {
                    _entities.Connection.Close();
                }
            }
            return data;
        }       

        

    }
}
